{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ebfb57ec-c9f5-4c3b-b9f6-98819506dedb",
   "metadata": {},
   "source": [
    "# Greeks and Sensitivity Analysis"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0bfc0241-b312-45cd-b1b6-cfecab9ad85e",
   "metadata": {},
   "source": [
    "# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d0d0add-ff03-4c37-af3c-3942c8adc582",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Load the Libs we need"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "4b0d19b3-7892-470c-8051-b3460605ed1a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# import Lib\n",
    "import pandas as pd\n",
    "import datetime as dt\n",
    "import pytz\n",
    "import os\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import yfinance as yf\n",
    "import numpy as np\n",
    "import scipy.stats as si\n",
    "import math\n",
    "import networkx as nx\n",
    "\n",
    "# import module\n",
    "from datetime import datetime, timezone\n",
    "from datetime import date, time\n",
    "from math import trunc\n",
    "from dateutil.parser import parse"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "741f3243-ed98-4d94-a939-4df9363c0090",
   "metadata": {},
   "source": [
    "## Calculating Greeks Using Python"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5eae75e1-3b9a-48dc-b1d6-b70b80f5848e",
   "metadata": {},
   "source": [
    "### Black-Scholes Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "cca04bc8-59d6-4d7a-a4d3-1fcc74861beb",
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "import numpy as np\n",
    "from scipy.stats import norm\n",
    "\n",
    "class mb_BlackScholes:\n",
    "    def __init__(self, S, K, r, T, v, q=0, t=0, option_type='call'):\n",
    "        self.S = S  # underlying asset price\n",
    "        self.K = K  # strike price\n",
    "        self.r = r  # risk-free interest rate\n",
    "        self.T = T  # time until expiration in years\n",
    "        self.v = v  # volatility\n",
    "        self.q = q  # dividend yield\n",
    "        self.t = t  # current time\n",
    "        self.option_type = option_type  # option type ('call' or 'put')\n",
    "        \n",
    "        # compute d1 and d2\n",
    "        self.d1 = ((np.log(self.S / self.K) + (self.r - self.q + 0.5 * self.v ** 2) * (self.T - self.t)) /\n",
    "                  (self.v * np.sqrt(self.T - self.t)))\n",
    "        self.d2 = self.d1 - self.v * np.sqrt(self.T - self.t)\n",
    "        \n",
    "    def price(self):\n",
    "        if self.option_type == 'call':\n",
    "            return (self.S * np.exp(-self.q * (self.T - self.t)) * norm.cdf(self.d1) - \n",
    "                    self.K * np.exp(-self.r * (self.T - self.t)) * norm.cdf(self.d2))\n",
    "        elif self.option_type == 'put':\n",
    "            return (self.K * np.exp(-self.r * (self.T - self.t)) * norm.cdf(-self.d2) - \n",
    "                    self.S * np.exp(-self.q * (self.T - self.t)) * norm.cdf(-self.d1))\n",
    "    \n",
    "    def delta(self):\n",
    "        if self.option_type == 'call':\n",
    "            return np.exp(-self.q * (self.T - self.t)) * norm.cdf(self.d1)\n",
    "        elif self.option_type == 'put':\n",
    "            return -np.exp(-self.q * (self.T - self.t)) * norm.cdf(-self.d1)\n",
    "        \n",
    "    def gamma(self):\n",
    "        return ((np.exp(-self.q * (self.T - self.t)) * norm.pdf(self.d1)) / \n",
    "               (self.S * self.v * np.sqrt(self.T - self.t)))\n",
    "        \n",
    "    def theta(self):\n",
    "        if self.option_type == 'call':\n",
    "            return (-((self.S * np.exp(-self.q * (self.T - self.t)) * norm.pdf(self.d1) * self.v) / (2 * np.sqrt(self.T - self.t))) - \n",
    "                    self.r * self.K * np.exp(-self.r * (self.T - self.t)) * norm.cdf(self.d2) + \n",
    "                    self.q * self.S * np.exp(-self.q * (self.T - self.t)) * norm.cdf(self.d1))\n",
    "        elif self.option_type == 'put':\n",
    "            return (-((self.S * np.exp(-self.q * (self.T - self.t)) * norm.pdf(self.d1) * self.v) / (2 * np.sqrt(self.T - self.t))) + \n",
    "                    self.r * self.K * np.exp(-self.r * (self.T - self.t)) * norm.cdf(-self.d2) - \n",
    "                    self.q * self.S * np.exp(-self.q * (self.T - self.t)) * norm.cdf(-self.d1))\n",
    "        \n",
    "    def vega(self):\n",
    "        return self.S * np.exp(-self.q * (self.T - self.t)) * norm.pdf(self.d1) * np.sqrt(self.T - self.t)\n",
    "    \n",
    "    def rho(self):\n",
    "        if self.option_type == 'call':\n",
    "            return self.K * (self.T - self.t) * np.exp(-self.r * (self.T - self.t)) * norm.cdf(self.d2)\n",
    "        elif self.option_type == 'put':\n",
    "            return -self.K * (self.T - self.t) * np.exp(-self.r * (self.T - self.t)) * norm.cdf(-self.d2)\n",
    "        \n",
    "# Second order Greeks\n",
    "    \n",
    "    def charm(self):\n",
    "        if self.option_type == 'call':\n",
    "            return -np.exp(-self.q * (self.T - self.t)) * norm.pdf(self.d1) * ((2 * (self.r - self.q) * (self.T - self.t) - self.d1 * self.v * np.sqrt(self.T - self.t)) / \n",
    "                    (2 * (self.T - self.t) * self.v * np.sqrt(self.T - self.t))) - self.q * np.exp(-self.q * (self.T - self.t)) * norm.cdf(self.d1)\n",
    "        elif self.option_type == 'put':\n",
    "            return -np.exp(-self.q * (self.T - self.t)) * norm.pdf(self.d1) * ((2 * (self.r - self.q) * (self.T - self.t) - self.d1 * self.v * np.sqrt(self.T - self.t)) / \n",
    "                    (2 * (self.T - self.t) * self.v * np.sqrt(self.T - self.t))) + self.q * np.exp(-self.q * (self.T - self.t)) * norm.cdf(-self.d1)\n",
    "        \n",
    "    def vomma(self):\n",
    "        return self.vega() * (self.d1 * self.d2 / self.v)\n",
    "    \n",
    "    def vanna(self):\n",
    "        return -np.exp(-self.q * (self.T - self.t)) * norm.pdf(self.d1) * self.d2 / self.v\n",
    "        \n",
    "    def speed(self):\n",
    "        return np.exp(-self.q * (self.T - self.t)) * norm.pdf(self.d1) / (self.S**2 * self.v * np.sqrt(self.T - self.t)) * (self.d1 + self.v * np.sqrt(self.T - self.t))\n",
    "        \n",
    "    def zomma(self):\n",
    "        return self.gamma() * ((self.d1 * self.d2 - 1) / self.v)\n",
    "    \n",
    "    def color(self):\n",
    "        return np.exp(-self.q * (self.T - self.t)) * norm.pdf(self.d1) / (2 * self.S * self.v * np.sqrt(self.T - self.t)) * (1 + self.d1 * ((2 * (self.r - self.q) * (self.T - self.t) - self.d2 * self.v * np.sqrt(self.T - self.t)) / \n",
    "                (2 * self.v * np.sqrt(self.T - self.t))))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "bb632899-6dda-4ac1-916f-4ace18ac9728",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Price:  7.491693155007894\n",
      "Delta:  0.5171512290359106\n",
      "Gamma:  0.019717640994265942\n",
      "Theta:  -5.637548457246437\n",
      "Vega:  39.435281988531884\n",
      "Rho:  44.223429748583165\n",
      "Charm:  -0.07299050034183298\n",
      "Vomma:  -1.5908834261433795\n",
      "Vanna:  0.28383706062941993\n",
      "Speed:  5.048685791412178e-05\n",
      "Zomma:  -0.09938364668440139\n",
      "Color:  0.010009108342042454\n"
     ]
    }
   ],
   "source": [
    "# Define option parameters\n",
    "S = 100  # underlying asset price\n",
    "K = 105  # strike price\n",
    "T = 1    # time until expiration in years\n",
    "r = 0.05 # risk-free interest rate\n",
    "q = 0.01 # dividend yield\n",
    "v = 0.20 # volatility\n",
    "\n",
    "# Calculate the Greeks using the extended BlackScholes class\n",
    "bs = mb_BlackScholes(S, K, r, T, v, q, option_type='call')\n",
    "\n",
    "print('Price: ', bs.price())\n",
    "print('Delta: ', bs.delta())\n",
    "print('Gamma: ', bs.gamma())\n",
    "print('Theta: ', bs.theta())\n",
    "print('Vega: ', bs.vega())\n",
    "print('Rho: ', bs.rho())\n",
    "\n",
    "# Calculate and print second-order Greeks\n",
    "print('Charm: ', bs.charm())\n",
    "print('Vomma: ', bs.vomma())\n",
    "print('Vanna: ', bs.vanna())\n",
    "print('Speed: ', bs.speed())\n",
    "print('Zomma: ', bs.zomma())\n",
    "print('Color: ', bs.color())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7bd18285-0edf-4abf-bd46-8289c3195dcf",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
